<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Trajectory Visualization with AMap</title>
    <style>
        body,
        html {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            font-family: Arial, sans-serif;
        }

        #container {
            width: 100%;
            height: 100%;
            position: relative;
        }

        #trajectoryMapContainer {
            width: 100%;
            height: 100%;
        }

        .control-panel {
            position: absolute;
            top: 20px;
            right: 20px;
            background: white;
            padding: 10px;
            border-radius: 4px;
            box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
            z-index: 100;
        }

        .time-control {
            position: absolute;
            bottom: 20px;
            left: 20px;
            right: 20px;
            background: white;
            padding: 10px;
            border-radius: 4px;
            box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
            z-index: 100;
        }

        button {
            padding: 5px 10px;
            margin: 0 5px;
            cursor: pointer;
        }

        .slider-container {
            width: 100%;
            margin-top: 10px;
        }

        .speed-control {
            margin-top: 10px;
        }

        .map-window__wrapper {
            padding: 10px;
            font-size: 14px;
        }

        .alert-title {
            font-weight: bold;
            color: #333;
        }

        .alert-time {
            color: #666;
            margin: 5px 0;
        }

        .alert-position {
            color: #999;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
            max-width: 200px;
        }

        .battery-info {
            display: flex;
            align-items: center;
            margin-top: 5px;
        }

        .battery {
            width: 40px;
            height: 16px;
            border: 1px solid #ccc;
            border-radius: 2px;
            margin-left: 5px;
            position: relative;
        }

        .battery.low-power {
            border-color: #ff4d4f;
        }

        .battery-level {
            height: 100%;
            background-color: #52c41a;
            transition: width 0.3s;
        }

        .battery.low-power .battery-level {
            background-color: #ff4d4f;
        }
    </style>
</head>

<body>
    <div id="container">
        <div id="trajectoryMapContainer"></div>

        <div class="control-panel">
            <button id="playBtn">Play</button>
            <button id="pauseBtn">Pause</button>
            <div class="speed-control">
                <label>Speed:</label>
                <select id="speedSelect">
                    <option value="1">1x</option>
                    <option value="2">2x</option>
                    <option value="5">5x</option>
                    <option value="10">10x</option>
                </select>
            </div>
        </div>

        <div class="time-control">
            <div class="slider-container">
                <input type="range" id="timeSlider" min="0" max="86400" step="1" value="0" style="width: 100%">
                <div id="timeDisplay">00:00:00</div>
            </div>
        </div>
    </div>

    <script src="https://webapi.amap.com/maps?v=2.0&key=6089b5b868160cd9820c162d02c1e10c"></script>
    <script src="https://webapi.amap.com/ui/1.1/main.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/dayjs@1/dayjs.min.js"></script>
    <script>
        // Initialize the map and trajectory visualization
        document.addEventListener('DOMContentLoaded', function () {
            // Sample trajectory data
            const trajectoryData = [
                {
                    "trackTime": "2025-06-30 11:14:31",
                    "longitude": 116.313228,
                    "latitude": 40.037606,
                    "speed": "0.0",
                    "angle": null,
                    "devicePower": null
                },
                {
                    "trackTime": "2025-06-30 11:15:31",
                    "longitude": 116.314228,
                    "latitude": 40.038606,
                    "speed": "1.5",
                    "angle": 45,
                    "devicePower": 80
                },
                {
                    "trackTime": "2025-06-30 11:16:31",
                    "longitude": 116.315228,
                    "latitude": 40.039606,
                    "speed": "2.0",
                    "angle": 60,
                    "devicePower": 75
                },
                {
                    "trackTime": "2025-06-30 11:17:31",
                    "longitude": 116.316228,
                    "latitude": 40.040606,
                    "speed": "2.5",
                    "angle": 75,
                    "devicePower": 70
                },
                {
                    "trackTime": "2025-06-30 11:18:31",
                    "longitude": 116.317228,
                    "latitude": 40.041606,
                    "speed": "3.0",
                    "angle": 90,
                    "devicePower": 65
                }
            ];

            // Initialize the map
            const map = new AMap.Map('trajectoryMapContainer', {
                resizeEnable: true,
                center: [116.313228, 40.037606],
                zoom: 15,
                animateEnable: true
            });

            // Format trajectory data
            function formatTrajectoryData(data) {
                // const startTimeStamp = dayjs(data[0].trackTime).startOf('day').unix();

                    // 计算当天开始时间戳
                    const startTimeStamp = new Date(data[0].trackTime).setHours(0, 0, 0, 0) / 1000;
                return data.map(item => {
                    
                    // const trackTime = dayjs(item.trackTime).valueOf();
                    const trackTime = new Date(item.trackTime).getTime();
                    return {
                        lng: item.longitude,
                        lat: item.latitude,
                        trackTime: trackTime,
                        second: trackTime / 1000 - startTimeStamp,
                        speed: item.speed,
                        angle: item.angle,
                        devicePower: item.devicePower,
                        time: new Date(trackTime).toLocaleTimeString(),
                        // time: dayjs(item.trackTime).format('HH:mm:ss')
                    };
                });
            }

            // Create markers and path
            const formattedData = formatTrajectoryData(trajectoryData);
            const path = formattedData.map(item => [item.lng, item.lat]);
            console.log('formattedData====', formattedData)
            console.log('path=============', path)
            // Create start and end markers
            const startMarker = new AMap.Marker({
                map: map,
                position: path[0],
                icon: 'https://webapi.amap.com/theme/v1.3/markers/n/start.png',
                offset: new AMap.Pixel(-13, -30)
            });

            const endMarker = new AMap.Marker({
                map: map,
                position: path[path.length - 1],
                icon: 'https://webapi.amap.com/theme/v1.3/markers/n/end.png',
                offset: new AMap.Pixel(-13, -30)
            });

            // Create polyline for the full path
            const polyline = new AMap.Polyline({
                map: map,
                path: path,
                strokeColor: '#3366FF',
                strokeWeight: 5,
                strokeStyle: 'solid'
            });

            // Fit view to show the entire path
            map.setFitView([polyline, startMarker, endMarker]);

            // Initialize PathSimplifier for animation
            AMapUI.load(['ui/misc/PathSimplifier'], function (PathSimplifier) {
                if (!PathSimplifier.supportCanvas) {
                    alert('Current environment does not support Canvas!');
                    return;
                }

                // Initialize path simplifier
                const pathSimplifier = new PathSimplifier({
                    zIndex: 100,
                    map: map,
                    getPath: function (pathData) {
                        return pathData.path;
                    },
                    getHoverTitle: function (pathData, pathIndex, pointIndex) {
                        return null;
                    },
                    renderOptions: {
                        pathLineStyle: {
                            dirArrowStyle: true
                        }
                    }
                });

                // Set path data
                pathSimplifier.setData([{
                    name: 'path',
                    path: path
                }]);

                // Create path navigator for animation
                const navg = pathSimplifier.createPathNavigator(0, {
                    loop: false,
                    speed: 100,
                    pathNavigatorStyle: {
                        width: 16,
                        height: 32,
                        content: PathSimplifier.Render.Canvas.getImageContent(
                            'https://webapi.amap.com/theme/v1.3/markers/n/mark_b.png',
                            function () {
                                pathSimplifier.renderLater();
                            },
                            function () {
                                alert('Image loading failed!');
                            }
                        ),
                        strokeStyle: null,
                        fillStyle: null,
                        pathLinePassedStyle: {
                            lineWidth: 6,
                            strokeStyle: '#3366FF',
                            dirArrowStyle: true
                        }
                    }
                });

                // Initialize UI controls
                const playBtn = document.getElementById('playBtn');
                const pauseBtn = document.getElementById('pauseBtn');
                const speedSelect = document.getElementById('speedSelect');
                const timeSlider = document.getElementById('timeSlider');
                const timeDisplay = document.getElementById('timeDisplay');

                // Update time display
                function updateTimeDisplay(seconds) {
                    const hours = Math.floor(seconds / 3600);
                    const minutes = Math.floor((seconds % 3600) / 60);
                    const secs = seconds % 60;

                    timeDisplay.textContent =
                        `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
                }

                // Set max value for time slider
                timeSlider.max = formattedData[formattedData.length - 1].second;

                // Play button click handler
                playBtn.addEventListener('click', function () {
                    navg.start();
                });

                // Pause button click handler
                pauseBtn.addEventListener('click', function () {
                    navg.pause();
                });

                // Speed change handler
                speedSelect.addEventListener('change', function () {
                    const speed = parseInt(this.value) * 100;
                    navg.setSpeed(speed);
                });

                // Time slider change handler
                timeSlider.addEventListener('input', function () {
                    const seconds = parseInt(this.value);
                    updateTimeDisplay(seconds);

                    // Find the closest point in the trajectory
                    let closestPoint = formattedData[0];
                    let minDiff = Math.abs(seconds - closestPoint.second);

                    for (let i = 1; i < formattedData.length; i++) {
                        const diff = Math.abs(seconds - formattedData[i].second);
                        if (diff < minDiff) {
                            minDiff = diff;
                            closestPoint = formattedData[i];
                        }
                    }

                    // Move the navigator to the closest point
                    const pointIndex = formattedData.indexOf(closestPoint);
                    navg.moveToPoint(pointIndex);
                });

                // Update time slider during animation
                navg.on('move', function (e) {
                    const currentPoint = formattedData[e.cursor.index];
                    timeSlider.value = currentPoint.second;
                    updateTimeDisplay(currentPoint.second);

                    // Show info window for the current point
                    const content = `
                        <div class="map-window__wrapper">
                            <div class="alert-info">
                                <span class="alert-title">Current Position</span>
                                ${currentPoint.devicePower !== null ? `
                                <div class="battery-info">
                                    <label>${currentPoint.devicePower}%</label>
                                    <div class="battery ${currentPoint.devicePower > 20 ? '' : 'low-power'}">
                                        <div class="battery-level" style="width: ${currentPoint.devicePower}%"></div>
                                    </div>
                                </div>
                                ` : ''}
                            </div>
                            <div class="alert-time">${currentPoint.time}</div>
                            <div class="alert-position">Speed: ${currentPoint.speed} m/s</div>
                        </div>
                    `;

                    const infoWindow = new AMap.InfoWindow({
                        content: content,
                        anchor: 'bottom-center',
                        offset: new AMap.Pixel(0, -40)
                    });

                    infoWindow.open(map, [currentPoint.lng, currentPoint.lat]);
                });

                // Start the animation
                navg.start();
            });
        });
    </script>
</body>

</html>